<?php
/**
 * 获取accesstoken
 */
namespace app\api\controller\v1;
use think\Controller;
use think\Request;
use app\api\controller\Api;
use think\Response;
use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use app\api\controller\Oauth as Oauth2;
//use app\api\model\Oauth as Oauth;
use app\common\model\ClientModel as Oauth;
use think\Db;
use think\Cache;
use app\api\controller\Factory;

class Token extends Controller
{	
	use Send;
    //appid和appsecret请求验证规则
    public static $rule_token = [
        'appid'       =>  'require',
        'appsecret'   =>  'require',
        'nonce'       =>  'require',
        'timestamp'   =>  'require',
    ];
    /**
     * 构造函数
     * 初始化检测请求时间，签名等
     */
    public function __construct()
    {
        $this->request = Request::instance();
        $this->checkTime();
        $this->checkSign();
    }
    /**
     * appid和appsecret 请求access_token
     */
    public function token()
    {
        //检测字段
        $this->checkAppkey(self::$rule_token);
        //获取客户端数据
        $appid = $this->request->param('appid');
        $appsecret = $this->request->param('appsecret');
        if( !empty($appid) && !empty($appsecret) ){
            $client = Oauth::get(['appid' => $appid,'status'=>1]);
            if(!empty($client)){
                try {
                    $client = $client->toArray();
                    $accessTokenInfo = $this->setAccessToken($client);
                    return $this->returnmsg(200,'success',$accessTokenInfo);
                } catch (\Exception $e) {
                    $this->sendError(500, 'server error!!', 500);
                }
            }else{
                return $this->returnmsg(401,'user is null');
            }
        }else{
            return $this->returnmsg(401,'user is null');
        }
    }

	/**
	 * 检测时间+_300秒内请求会异常
	 */
	public function checkTime()
	{
		$time = $this->request->param('timestamp');
		if($time > time()+300  || $time < time()-300){
			return $this->returnmsg(401,'The requested time is incorrect');
		}
	}

	/**
	 * 检测appkey的有效性
	 * @param 验证规则数组
	 */
	public function checkAppkey($rule)
	{
		$result = $this->validate($this->request->param(),$rule);
		if(true !== $result){
			return $this->returnmsg(405,$result);
		}
        //调用模型验证app_key是否正确
//		 $result = Oauth::get(function($query){
//		 	$query->where('appid', $this->request->param('appid'));
//		 	$query->where('expire_time','>' ,time());
//		 });
//		if(empty($result)){
//			return $this->returnmsg(401,'appid does not exist or has expired. Please contact management');
//		}
	}

	/**
	 * 检查签名
	 */
	public function checkSign()
	{	
		$baseAuth = Factory::getInstance(\app\api\controller\Oauth::class);
		$app_secret = Oauth::get(['appid' => $this->request->param('appid')]);
    	$sign = $baseAuth->makesign($this->request->param(),$app_secret['appsecret']);     //生成签名
    	if($sign !== $this->request->param('signature')){
    		return self::returnmsg(401,'Signature error',[],[]);
    	}
	}

	/**
     * 设置AccessToken
     * @param $clientInfo
     * @return int
     */
    protected function setAccessToken($clientInfo)
    {
        //生成令牌
        $accessToken = self::buildAccessToken();
        $accessTokenInfo = [
            'access_token' => $accessToken,//访问令牌
            'expires_time' => time() + Oauth2::$expires,      //过期时间时间戳
            'client' => $clientInfo,//用户信息
        ];
        self::saveAccessToken($accessTokenInfo);
        return $accessTokenInfo;
    }

    /**
     * 生成AccessToken
     * @return string
     */
    protected static function buildAccessToken($lenght = 32)
    {
        //生成AccessToken
        $str_pol = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmnopqrstuvwxyz";
		return substr(str_shuffle($str_pol), 0, $lenght);
    }
    /**
     * 存储
     * @param $accessToken
     * @param $accessTokenInfo
     */
    protected static function saveAccessToken($accessTokenInfo)
    {
        $data['uid'] = $accessTokenInfo['client']['uid'];
        $data['access_token'] = $accessTokenInfo['access_token'];
        $data['expire_time'] = $accessTokenInfo['expires_time'];
        Oauth::update($data);
    }
}